﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using Pixysoft.Framework.Verifications;


namespace Pixysoft.Framework.XSchEmA.Entity
{
    /// <summary>
    /// foreign key schema
    /// </summary>
    public class ForeignKeySchema
    {
        private string constraintName;//源

        private string fkTableName;//源
        private List<string> fkColumnNames = new List<string>();

        private TableSchema fkTable;
        private List<ColumnSchema> fkColumns = new List<ColumnSchema>();


        private string pkeyConsName;//目标

        private string pkTableName;//目标
        private List<string> pkColumnNames = new List<string>();//目标

        private TableSchema pkTable;
        private List<ColumnSchema> pkColumns = new List<ColumnSchema>();


        /// <summary>
        /// constraint name
        /// </summary>
        [XmlAttribute]
        public string ConsName
        {
            get { return constraintName; }
            set { constraintName = value; }
        }
        /// <summary>
        /// foreign table name: modify tablename XXX
        /// </summary>
        [XmlAttribute]
        public string FkTableName
        {
            get { return fkTableName; }
            set { fkTableName = value; }
        }
        /// <summary>
        /// foreign table column name: mdoify tablename add constraint foreign key(columnnames) XXX
        /// </summary>
        [XmlArray]
        public List<string> FkColumnNames
        {
            get { return fkColumnNames; }
            set { fkColumnNames = value; }
        }

        /// <summary>
        /// 目标约束名。references constraint name (unique, index, primarykey)
        /// </summary>
        [XmlAttribute]
        public string PkeyConsName
        {
            get { return pkeyConsName; }
            set { pkeyConsName = value; }
        }
        [XmlAttribute]
        public string PkTableName
        {
            get { return pkTableName; }
            set { pkTableName = value; }
        }
        [XmlArray]
        public List<string> PkColumnNames
        {
            get { return pkColumnNames; }
            set { pkColumnNames = value; }
        }


        /// <summary>
        /// 源表
        /// </summary>
        /// <value>The fk table.</value>
        [XmlIgnore]
        public TableSchema FkTable
        {
            get { return fkTable; }
            set { fkTable = value; }
        }
        /// <summary>
        /// 源列
        /// </summary>
        /// <value>The fk column.</value>
        [XmlIgnore]
        public List<ColumnSchema> FkColumns
        {
            get { return fkColumns; }
            set { fkColumns = value; }
        }


        [XmlIgnore]
        public TableSchema PkTable
        {
            get { return pkTable; }
            set { pkTable = value; }
        }
        [XmlIgnore]
        public List<ColumnSchema> PkColumns
        {
            get { return pkColumns; }
            set { pkColumns = value; }
        }


        /// <summary>
        ///  foreign key schema
        /// </summary>
        public ForeignKeySchema() { }
        /// <summary>
        /// foreign key schema
        /// </summary>
        /// <param name="fkName"></param>
        /// <param name="pConsName"></param>
        /// <param name="fkTableName"></param>
        /// <param name="fkColumnNames"></param>
        public ForeignKeySchema(string fkName)
        {
            this.constraintName = fkName;
        }
        /// <summary>
        /// check schema
        /// </summary>
        public void Inspection()
        {
            if (!Verification.Verifies(constraintName, pkeyConsName, fkTableName, fkTable, pkTable, fkColumnNames, pkColumnNames, fkColumns, pkColumns).IsNotNullOrEmpty().Result())
                throw Exceptions.VerificationFailedException(constraintName, pkeyConsName, fkTableName, fkTable, pkTable, fkColumnNames, pkColumnNames, fkColumns, pkColumns);

            if (fkColumnNames.Count == 0)
                throw Exceptions.VerificationFailedException(fkColumnNames);

            if (FkColumnNames.Count != FkColumns.Count)
                throw Exceptions.VerificationFailedException(fkColumnNames, fkColumns);

            if (pkColumnNames.Count == 0)
                throw Exceptions.VerificationFailedException(pkColumnNames);

            if (pkColumnNames.Count != pkColumns.Count)
                throw Exceptions.VerificationFailedException(pkColumnNames, pkColumns);
        }
        /// <summary>
        /// refresh schema by pointer
        /// </summary>
        public void Refresh()
        {
            if (!Verification.Verifies(fkTable, pkTable, fkColumns, pkColumns).IsNotNullOrEmpty().Result())
                throw Exceptions.VerificationFailedException(fkTable, pkTable, fkColumns, pkColumns);

            FkTableName = fkTable.TableName;

            pkTableName = pkTable.TableName;

            FkColumnNames = new List<string>();

            PkColumnNames = new List<string>();

            foreach (ColumnSchema column in FkColumns)
                FkColumnNames.Add(column.ColumnName);

            foreach (ColumnSchema column in PkColumns)
                PkColumnNames.Add(column.ColumnName);
        }
        /// <summary>
        /// to string
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return ConsName + ":" + pkeyConsName;
        }
        /// <summary>
        /// clone
        /// </summary>
        /// <returns></returns>
        public ForeignKeySchema Clone()
        {
            ForeignKeySchema fk = new ForeignKeySchema(ConsName);

            fk.FkTableName = this.FkTableName;

            foreach (string columnName in this.fkColumnNames)
                fk.fkColumnNames.Add(columnName);

            fk.pkeyConsName = this.pkeyConsName;

            fk.pkTableName = this.pkTableName;

            foreach (string columnName in this.pkColumnNames)
                fk.pkColumnNames.Add(columnName);

            return fk;

        }
    }
}
